﻿using Microsoft.EntityFrameworkCore;
using RotovapPlatform.Domain.Business.Interfaces;
using RotovapPlatform.Domain.Business.Storage.Entities;
using RotovapPlatform.Domain.Business.Storage.Enums;
using RotovapPlatform.Infrastructure.Common.Data;
using static RotovapPlatform.Domain.Business.Machine.Enums.ExperimentConfigEnums;

namespace RotovapPlatform.Infrastructure.Business.Storage;

public class StorageLocationRepository : IStorageLocationRepository
{
	private readonly StorageDbContext _context;

	public StorageLocationRepository(StorageDbContext context)
	{
		_context = context;
	}

	public async Task<StorageLocation?> GetByIdAsync(int id)
	{
		return await _context.StorageLocations.FindAsync(id);
	}

	public async Task<IEnumerable<StorageLocation>> GetAllAsync()
	{
		return await _context.StorageLocations.ToListAsync();
	}

	public async Task AddAsync(StorageLocation location)
	{
		await _context.StorageLocations.AddAsync(location);
		await _context.SaveChangesAsync();
	}

	public async Task UpdateAsync(StorageLocation location)
	{
		// 修复实体跟踪冲突问题
		var entry = _context.Entry(location);
		if (entry.State == EntityState.Detached)
		{
			// 首先从数据库中获取最新数据
			var freshData = await _context.StorageLocations
				.AsNoTracking()
				.FirstOrDefaultAsync(e => e.Id == location.Id);

			if (freshData == null)
			{
				throw new InvalidOperationException($"无法更新ID为{location.Id}的StorageLocation，数据库中不存在该记录");
			}

			// 查找当前上下文中是否已跟踪该实体
			var attachedEntity = _context.Set<StorageLocation>()
				.Local.FirstOrDefault(e => e.Id == location.Id);

			if (attachedEntity != null)
			{
				// 找到了已跟踪的实体，更新其属性值
				_context.Entry(attachedEntity).CurrentValues.SetValues(location);

				// 特别确保IsReserved值被正确设置
				_context.Entry(attachedEntity).Property(x => x.IsReserved).IsModified = true;
			}
			else
			{
				// 没有找到已跟踪的实体，使用Attach和State
				_context.Set<StorageLocation>().Attach(location);
				entry.State = EntityState.Modified;
			}
		}
		else if (entry.State == EntityState.Unchanged)
		{
			// 实体被跟踪但未修改，标记为已修改
			entry.State = EntityState.Modified;

			// 特别确保IsReserved值被正确设置
			entry.Property(x => x.IsReserved).IsModified = true;
		}
		else if (entry.State == EntityState.Modified)
		{
			// 确保IsReserved标记为已修改
			entry.Property(x => x.IsReserved).IsModified = true;
		}

		// 先刷新数据变更到数据库
		await _context.SaveChangesAsync();

		// 清除上下文缓存
		_context.ChangeTracker.Clear();
	}

	public async Task DeleteAsync(int id)
	{
		var location = await GetByIdAsync(id);
		if (location != null)
		{
			_context.StorageLocations.Remove(location);
			await _context.SaveChangesAsync();
		}
	}

	public async Task<StorageLocation?> GetByPositionAsync(LocationCode locationCode, int position, bool forceRefresh = false)
	{
		if (forceRefresh)
		{
			// 使用AsNoTracking()避免EF Core跟踪实体，每次都从数据库读取最新数据
			return await _context.StorageLocations
				.AsNoTracking()
				.FirstOrDefaultAsync(x => x.LocationCode == locationCode && x.Position == position);
		}
		else
		{
			return await _context.StorageLocations
				.FirstOrDefaultAsync(x => x.LocationCode == locationCode && x.Position == position);
		}
	}

	public async Task<IEnumerable<StorageLocation>> GetByLocationCodeAsync(LocationCode locationCode, bool forceRefresh = false)
	{
		if (forceRefresh)
		{
			// 使用AsNoTracking()避免EF Core跟踪实体，每次都从数据库读取最新数据
			return await _context.StorageLocations
				.AsNoTracking()
				.Where(x => x.LocationCode == locationCode)
				.ToListAsync();
		}
		else
		{
			return await _context.StorageLocations
				.Where(x => x.LocationCode == locationCode)
				.ToListAsync();
		}
	}

	public async Task<List<StorageLocation>> GetByItemTypeAsync(ItemType itemType)
	{
		return await _context.StorageLocations
			.Where(x => x.SupportedItemTypes.Contains(itemType))
			.ToListAsync();
	}

	public async Task<StorageLocation?> FindEmptyLocationForItemAsync(ItemType itemType)
	{
		return await _context.StorageLocations
			.Where(x => !x.IsOccupied
				&& x.IsReserved == 0
				&& x.SupportedItemTypes.Contains(itemType))
			.FirstOrDefaultAsync();
	}
}